﻿using ExpressionPlotterControl;
using MathMLToCSharp;
using MathMLToCSharp.Entities;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.Linq;

namespace SMART_VIET_V01
{
    public partial class frm_tuychinhdothi : Form
    {
        frm_vedothi parent;
        exobj obj;
        string xml = "";
        string expression;
        Color[] colorLevels = { Color.Red,  Color.Green, Color.Blue,  
            Color.Purple, Color.Brown, Color.Orange, Color.Chocolate, 
            Color.Maroon, Color.Navy, Color.YellowGreen };
        string[] strFunctions ={ "abs", "sin", "cos", "tan", "sec", "cosec", "cot", "arcsin", 
            "arccos", "arctan", "exp", "ln", "log", "antilog", "sqrt", "sinh", "cosh", "tanh", 
            "arcsinh", "arccosh", "arctanh" };

        public frm_tuychinhdothi(frm_vedothi parent)
        {
            this.parent = parent;
            InitializeComponent();
        }
        public frm_tuychinhdothi(frm_vedothi parent, exobj obj)
        {
            this.obj = obj;
            this.parent = parent;
            InitializeComponent();
            txtName.Text = obj.name;
            clNet.EditValue = obj.color;
            txtExpression.Text = obj.ex;
        }
        private void bt_huy_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void bt_chapnhan_Click(object sender, EventArgs e)
        {
            string ex = "";
            try
            {
                xml = dksMathEditor1.textResult();
                ex = getvalue();
            }
            catch (Exception)
            {
                xml = "";
                ex = txtExpression.Text;
            }

            if (txtName.Text.Length == 0)
            {
                MessageBox.Show("Bạn chưa đặt tên cho đồ thị!", "Cảnh báo!");
                return;
            }
            if (obj != null)
            {
                obj.ex = txtExpression.Text;
                obj.color = (Color)clNet.EditValue;
                obj.name = txtName.Text;
                obj.exIE = (IEvaluatable)new Expression(ex);
                obj.xml = xml;
                parent.UpdateExpressions(obj);
            }
            else
            {
                parent.AddExpression(ex, (Color)clNet.EditValue, txtName.Text, xml);
            }
            parent.Refresh();
            parent.Activate();
            this.Close();

        }

        private void txtExpression_TextChanged(object sender, EventArgs e)
        {
            int cursorPosition = this.txtExpression.SelectionStart;
            WriteText(this.txtExpression.Text);
            this.txtExpression.SelectionStart = cursorPosition;
        }

        private void txtExpression_KeyPress(object sender, KeyPressEventArgs e)
        {
            //if (e.KeyChar == 13 && txtExpression.Text.Length > 0)
            //    AddExpression();

            //if a letter is found
            if (char.IsLetter(e.KeyChar))
            {
                int cursorPos = this.txtExpression.SelectionStart;
                if (cursorPos > 0)
                {
                    //if the previous char is a digit, add a *
                    if (char.IsDigit(this.txtExpression.Text[cursorPos - 1]))
                    {
                        this.txtExpression.Text = this.txtExpression.Text.Insert(cursorPos, "*" + e.KeyChar);
                        cursorPos += 2;
                        this.txtExpression.SelectionStart = cursorPos;
                        e.Handled = true;
                    }
                    //if a function is formed, add a "("
                    else
                    {
                        string text = string.Empty;
                        int i = cursorPos - 1;
                        while (i >= 0)
                        {
                            if (!char.IsLetter(this.txtExpression.Text[i]))
                                break;
                            i--;
                        }
                        i++;
                        //now i is the index where last text is started
                        if (i < cursorPos)
                            text = this.txtExpression.Text.Substring(i, cursorPos - i) + e.KeyChar;
                        if (IsFunction(text))
                        {
                            this.txtExpression.Text = this.txtExpression.Text.Insert(cursorPos, e.KeyChar.ToString() + "(");
                            cursorPos += 2;
                            this.txtExpression.SelectionStart = cursorPos;
                            e.Handled = true;
                        }
                    }
                }
            }
        }
        #region Helper Functions
        //this functions handles coloring of expressions
        private void WriteText(string text)
        {
            int colorIndex = 0;
            this.txtExpression.Text = "";
            for (int i = 0; i < text.Length; i++)
            {
                if (text[i] == '(')
                {
                    colorIndex++;
                    if (colorIndex == colorLevels.Length)
                        colorIndex = 0;
                    txtExpression.SelectionColor = colorLevels[colorIndex];
                }

                this.txtExpression.AppendText(text[i].ToString());

                if (text[i] == ')')
                {
                    colorIndex--;
                    if (colorIndex < 0)
                        colorIndex = colorLevels.Length - 1;
                    txtExpression.SelectionColor = colorLevels[colorIndex];
                }
            }
        }

        private bool IsFunction(string text)
        {
            for (int i = 0; i < strFunctions.Length; i++)
                if (string.Compare(text, strFunctions[i], true) == 0)
                    return true;
            return false;
        }

        private void AddExpression()
        {
            if (this.txtExpression.Text.Length == 0)
                return;
            this.txtExpression.Text = CompleteParenthesis(this.txtExpression.Text);
            string expText = this.txtExpression.Text;
            IEvaluatable exp = new Expression(expText);
            if (!exp.IsValid)
            {
                if (MessageBox.Show("The expression entered does not seem to be valid, do you still want to add it?", "ValidationError", MessageBoxButtons.YesNo) == DialogResult.No)
                    return;
            }
            this.txtExpression.Text = string.Empty;
        }
        private string CompleteParenthesis(string exp)
        {
            int leftBracket = 0;
            int rightBracket = 0;
            for (int i = 0; i < exp.Length; i++)
            {
                if (exp[i] == '(')
                    leftBracket++;
                else if (exp[i] == ')')
                    rightBracket++;
            }
            exp = exp.PadRight(exp.Length + leftBracket - rightBracket, ')');
            return exp;
        }
        public string getvalue()
        {
            string result = "";
            try
            {
                string text = dksMathEditor1.textResult();
                text = text.Replace("<mtable><mtr><mtd>", "");
                text = text.Replace("</mtd></mtr></mtable>", "");
                result = ParseAndOutput(text);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            return result;
        }
        private static string ParseAndOutput(string mathML)
        {
            return ParseAndOutput(mathML, new BuildContextOptions());
        }
        private DevExpress.XtraTab.XtraTabPage xtraTabPage1;
        private DKSMathEditor.DKSMathEditor dksMathEditor1;
        private void addTab()
        {
            if (tab.TabPages.Count == 1)
            {
                this.xtraTabPage1 = new DevExpress.XtraTab.XtraTabPage();
                this.dksMathEditor1 = new DKSMathEditor.DKSMathEditor();
                // 
                // xtraTabPage1
                // 
                this.xtraTabPage1.Controls.Add(this.dksMathEditor1);
                this.xtraTabPage1.Name = "xtraTabPage1";
                this.xtraTabPage1.Size = new System.Drawing.Size(498, 175);
                this.xtraTabPage1.Text = "MathML";
                // 
                // dksMathEditor1
                // 
                this.dksMathEditor1.Dock = System.Windows.Forms.DockStyle.Fill;
                this.dksMathEditor1.Location = new System.Drawing.Point(0, 0);
                this.dksMathEditor1.Name = "dksMathEditor1";
                this.dksMathEditor1.TabIndex = 1;
                this.dksMathEditor1.ViewCode = false;
                this.dksMathEditor1.ViewCodeClick += new System.EventHandler(this.dksMathEditor1_ViewCodeClick);
                this.xtraTabPage1.ShowCloseButton = DevExpress.Utils.DefaultBoolean.True;
                //load xml
                if (obj !=null && obj.xml.Length > 1)
                {
                    this.dksMathEditor1.LoadXML(obj.xml);
                }

            }
        }
        private void removetab()
        {

        }
        //backgroundworker

        //
        #endregion
        private static string ParseAndOutput(string mathML, BuildContextOptions options)
        {
            mathML = mathML.Replace("&", "");
            mathML = mathML.Replace(";", "");
            mathML = mathML.Replace("plus", "+");
            mathML = mathML.Replace("minus", "-");
            mathML = mathML.Replace("times", "*");
            mathML = mathML.Replace("sol", "/");
            mathML = mathML.Replace("lbrace", "{");
            mathML = mathML.Replace("rbrace", "}");
            mathML = mathML.Replace("lpar", "(");
            mathML = mathML.Replace("rpar", ")");
            mathML = mathML.Replace("verbar", "|");
            mathML = mathML.Replace("lbrack", "[");
            mathML = mathML.Replace("rbrack", "]");
            mathML = mathML.Replace("excl", "!");
            mathML = mathML.Replace("sim", "~");
            mathML = mathML.Replace("equals", "=");
            mathML = mathML.Replace("amp", "&");
            mathML = mathML.Replace("num", "#");
            mathML = mathML.Replace("comma", ",");
            mathML = mathML.Replace("af", "&#8289;");
            IBuildable b = Parser.Parse(XElement.Parse(mathML));
            StringBuilder sb = new StringBuilder();
            b.Visit(sb, new BuildContext(options));
            return sb.ToString();
        }
        private void dksMathEditor1_ViewCodeClick(object sender, EventArgs e)
        {
            tab.SelectedTabPage = this.xtraTabPage2;
            txtExpression.Text = getvalue();
        }

        private void btGiaoDien_Click(object sender, EventArgs e)
        {
            picLoading.Visible = true;
            backgroundWorker1.RunWorkerAsync();
        }

        private void frm_tuychinhdothi_FormClosing(object sender, FormClosingEventArgs e)
        {
            this.Dispose();
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            addTab();
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (tab.TabPages.Count > 1)
            {
                this.tab.SelectedTabPage = this.xtraTabPage1;
            }
            else
            {
                this.tab.TabPages.Add(xtraTabPage1);
                this.tab.SelectedTabPage = this.xtraTabPage1;
            }
            picLoading.Visible = false;
        }


    }
}
